package com.Touch.tuio
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Stage;
	import flash.events.DataEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.geom.Point;
	import flash.net.XMLSocket;

	public class TUIOManager extends EventDispatcher
	{
		//-------------------------------------------------
		/*                   单例模式                    */
		//-------------------------------------------------
		private static var tuio:TUIOManager;
		public static function getTUIO():TUIOManager{
			if(tuio==null){
				tuio=new TUIOManager();
			}
			return tuio;
		}
		
		public static function TUIOinit(s:DisplayObjectContainer, host:String="127.0.0.1", port:Number=3000):void{
			return getTUIO().init(s,host,port);
		}
		
		public static function getObjectByID(id:Number):TUIOObject{
			return getTUIO().getObjectById(id);
		}
		//-------------------------------------------------
		
		private var FLOSCSocket:XMLSocket;		
		private var FLOSCSocketHost:String;			
		private var FLOSCSocketPort:Number;	
		
		private var thestage:Stage;
		private var objectArray:Vector.<TUIOObject>;
		private var recordedXML:XML;
		
		
		public function TUIOManager()
		{
			objectArray=new Vector.<TUIOObject>();
			recordedXML = <OSCPackets></OSCPackets>;
		}
		
		public function init(s:DisplayObjectContainer, host:String, port:Number):void{
			FLOSCSocketHost=host;			
			FLOSCSocketPort=port;		
			thestage = s.stage; // 获取当然文档类的舞台					
			
			try
			{
				// 与服务端建立xml socket连接
				FLOSCSocket = new XMLSocket();
				
				FLOSCSocket.addEventListener(Event.CLOSE, closeHandler);
				FLOSCSocket.addEventListener(Event.CONNECT, connectHandler);
				FLOSCSocket.addEventListener(DataEvent.DATA, dataHandler);
				FLOSCSocket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				FLOSCSocket.addEventListener(ProgressEvent.PROGRESS, progressHandler);
				FLOSCSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				
				FLOSCSocket.connect(host, port);
			} catch (e:Error)
			{
			}
		}
		
		//--------------------------------------------------------------------
		/*                      socket事件处理                              */
		//--------------------------------------------------------------------
		private function closeHandler(event:Event):void {
			
		}
		private function connectHandler(event:Event):void {
			
		}
		private function dataHandler(event:DataEvent):void {
			recordedXML.appendChild(XML(event.data));
			processMessage(XML(event.data));
		}
		private function ioErrorHandler(event:IOErrorEvent):void {	
			//"没有连接到TUIO设备或TUIO服务！请检查设备或程序！
		}
		private function progressHandler(event:ProgressEvent):void {
			//trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
		}
		private function securityErrorHandler(event:SecurityErrorEvent):void {			
		}
		//----------------------------------------------------------------------
		
		//--------------------------------------------------------------------
		/*                        功能处理模块                              */
		//--------------------------------------------------------------------
		// 这个是最重要的数据处理函数
		public function processMessage(msg:XML):void
		{
			var node:XML;
			trace(msg);
			return;
			
			///			trace("fseq = " + fseq);
			
			// 处理alive消息，格式如下：
			//
			// uio/[profileName] alive [list of active sessionIDs]
			// profileName 代表定义好的常用可感知用户界面配置
			// alive 消息标示
			// [list of active sessionIDs] 一系列当前有用的目标对象的id号
			
			for each(node in msg.MESSAGE)
			{
				if(node.ARGUMENT[0] && node.ARGUMENT[0].@VALUE == "alive")
				{
					// 重置objectArray数组中存储的所有TUIOOject实例的isAlive属性
					for each (var obj1:TUIOObject in objectArray)
					{
						obj1.isAlive = false;
					}
					
					for each(var aliveItem:XML in node.ARGUMENT.(@VALUE != "alive"))
					{
						// 根据alive消息中的id，相应的TUIOObject实例的isAlive属性设置为true，也即是当前点可用
						if(getObjectById(aliveItem.@VALUE))
							getObjectById(aliveItem.@VALUE).isAlive = true;
						
					}
				}
			}			
			
			// 处理set消息				
			for each(node in msg.MESSAGE)
			{
				if(node.ARGUMENT[0])
				{
					var type:String;
					// /tuio/2Dcur set s x y X Y m
					if(node.@NAME == "/tuio/2Dcur")
					{
						type = node.ARGUMENT[0].@VALUE;				
						
						// 判断消息类型是否为set
						if(type == "set") 
						{
							// 当前点的id并转换需要的数据
							var id_2:int = node.ARGUMENT[1].@VALUE
							var x_2:Number = Number(node.ARGUMENT[2].@VALUE) * thestage.stageWidth;
							var y_2:Number = Number(node.ARGUMENT[3].@VALUE) * thestage.stageHeight;
							var X_2:Number = Number(node.ARGUMENT[4].@VALUE);
							var Y_2:Number = Number(node.ARGUMENT[5].@VALUE);
							var m_2:int = node.ARGUMENT[6].@VALUE;
							var stagePoint_2:Point = new Point(x_2, y_2);	
							
							// 根据返回的数组，得到最上层的显示对象
							var displayObjArray_2:Array = thestage.getObjectsUnderPoint(stagePoint_2);
							var dobj_2:DisplayObject = null;
							if(displayObjArray_2.length > 0)								
								dobj_2 = displayObjArray_2[displayObjArray_2.length-1];
							
							// 根据当前id号在objectArray数组中查找是否存在对于的TUIOOjbect实例
							var tuioobj_2:TUIOObject = getObjectById(id_2);
							
							if(tuioobj_2 == null)
							{
								// 不存在，则创建响应TUIOObject对象
								new TUIOObject("2Dcur", id_2, x_2, y_2, X_2, Y_2, -1, 0, dobj_2);							
								objectArray.push(tuioobj_2);
								
								// 发送TUIO_OVER和TUIO_DOWN消息（请结合TUIOObject代码来理解）
								tuioobj_2.notifyCreated();
							} 
							else 
							{
								// 存在，则更新当前点的信息
								tuioobj_2.x = x_2;
								tuioobj_2.y = y_2;							
								tuioobj_2.dX = X_2;
								tuioobj_2.dY = Y_2;
								
								tuioobj_2.setObjOver(dobj_2);
								tuioobj_2.notifyMoved();
							}  
							
							try
							{
								// 发送TUIO_MOVE消息
								if(tuioobj_2.obj && tuioobj_2.obj.parent)
								{							
									var localPoint_2:Point = tuioobj_2.obj.parent.globalToLocal(stagePoint_2);							
									tuioobj_2.obj.dispatchEvent(new TUIOEvent(TUIOEvent.TUIO_MOVE, true, false, x_2, y_2, localPoint_2.x, localPoint_2.y, tuioobj_2.oldX, tuioobj_2.oldY, tuioobj_2.obj, false,false,false, true, m_2, "2Dobj", id_2,-1,0));
								}
							} catch (e:Error)
							{}
						}
					}
				}
			}
			
			
			// 如果当前点非alive，则总objectArray数组中去掉，并且清楚当前点。
			for (var i:int=0; i<objectArray.length; i++ )
			{
				if(objectArray[i].isAlive == false)
				{
					objectArray[i].kill();
					objectArray.splice(i, 1);
					i--;
				} 
			}
		}
		
		// 从名字就可以看出来函数功能。根据id来查找所有存储在objectArray数组中的TUIOObject实例
		public function getObjectById(id:Number): TUIOObject
		{
			for each(var i:TUIOObject in objectArray){
				if(i.ID==id){
					return i;
				}
			}
			return null;
		}
	}
}